﻿using MVCHelperExtensions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Savvy.TestExtensions;
using System.Collections;
using System.Collections.Generic;

namespace MVCHelperExtensions.Test
{    
    /// <summary>
    ///This is a test class for MVCHelperUtilitiesTest and is intended
    ///to contain all MVCHelperUtilitiesTest Unit Tests
    ///</summary>
  [TestClass()]
  public class MVCHelperUtilitiesTest
  {
    #region GetModelID tests
    [TestMethod()]
    public void GetModelID_should_return_a_valid_id_for_the_given_model_instance()
    {
      var modelInstance = new TestModel() { ID = 1 };
      Assert.AreEqual(1, MVCHelperUtilities.GetModelID(modelInstance));
    }
    
    [TestMethod()]
    public void GetModelID_should_return_valid_id_for_the_model_instance_with_Id_property()
    {
      var modelInstance = new TestModelWithId() { Id = 1 };
      Assert.AreEqual(1, MVCHelperUtilities.GetModelID(modelInstance));
    }

    [TestMethod()]
    public void GetModelID_should_return_valid_id_for_the_model_instance_with_id_property()
    {
      var modelInstance = new TestModelWithid() { id = 1 };
      Assert.AreEqual(1, MVCHelperUtilities.GetModelID(modelInstance));
    }

    [TestMethod()]
    public void GetModelID_should_return_valid_id_for_the_model_instance_with__ID_property()
    {
      var modelInstance = new TestModelWith_ID() { _ID = 1 };
      Assert.AreEqual(1, MVCHelperUtilities.GetModelID(modelInstance));
    }

    [TestMethod()]
    public void GetModelID_should_return_valid_id_for_the_model_instance_with__Id_property()
    {
      var modelInstance = new TestModelWith_Id() { _Id = 1 };
      Assert.AreEqual(1, MVCHelperUtilities.GetModelID(modelInstance));
    }

    [TestMethod()]
    public void GetModelID_should_return_valid_id_for_the_model_instance_with__id_property()
    {
      var modelInstance = new TestModelWith_id() { _id = 1 };
      Assert.AreEqual(1, MVCHelperUtilities.GetModelID(modelInstance));
    }

    [TestMethod()]
    public void GetModelID_should_return_valid_id_for_the_model_instance_with_an_alternate_id_property()
    {
      var modelInstance = new TestModelWithAlternateID() { AlternateID = 1 };
      Assert.AreEqual(1, MVCHelperUtilities.GetModelID(modelInstance));
    }

    [TestMethod()]
    public void GetModelID_should_raise_exception_if_model_instance_has_no_discernable_id_property()
    {
      var modelInstance = new TestModelWithoutID();
      AssertExtensions.AssertThrows<NonInferrableModelIdException>(
        () => { MVCHelperUtilities.GetModelID(modelInstance); }
      );
    }

    [TestMethod()]
    public void GetModelID_should_raise_exception_if_id_property_is_not_an_integer()
    {
      var modelInstance = new TestModelWithInvalidID();
      AssertExtensions.AssertThrows<NonInferrableModelIdException>(
        () => { MVCHelperUtilities.GetModelID(modelInstance); }
      );      
    }
    #endregion

    #region GetControllerName tests

    [TestMethod()]
    public void GetControllerName_should_return_pluralized_form_of_model_class_name_if_model_instance_has_no_controller_name_attribute()
    {
      var modelInstance = new TestModel();
      Assert.AreEqual("TestModels", MVCHelperUtilities.GetControllerName(modelInstance.GetType()));
    }

    [TestMethod()]
    public void GetControllerName_should_return_a_valid_controller_name_for_the_given_class_with_controller_name_attribute()
    {
      var modelInstance = new TestModelWithControllerName_OtherController();
      Assert.AreEqual("OtherController", MVCHelperUtilities.GetControllerName(modelInstance.GetType()));
    }
    #endregion

    #region GetClassAttribute tests
    [TestMethod()]
    public void GetClassAttribute_should_return_null_if_class_has_no_attribute_of_the_given_type()
    {
      var modelInstance = new TestModel();
      Assert.AreEqual(null, MVCHelperUtilities.GetClassAttribute<MVCHelperControllerNameAttribute>(modelInstance.GetType()));
    }

    [TestMethod()]
    public void GetClassAttribute_should_return_a_valid_attribute_for_a_class_with_the_given_attribute_type()
    {
      var modelInstance = new TestModelWithControllerName_OtherController();
      Assert.IsNotNull(MVCHelperUtilities.GetClassAttribute<MVCHelperControllerNameAttribute>(modelInstance.GetType()));
    }
    #endregion

    #region ObjectToDictionary tests
    [TestMethod()]
    public void ObjectToDictionary_should_return_valid_Dictionary()
    {
      var anonymousHTMLAttributes = new { id = 1, name = "test" };

      IDictionary<string, object> actual = 
        MVCHelperUtilities.ObjectToDictionary(anonymousHTMLAttributes);

      Assert.IsTrue(((int)actual["id"]) == 1);
      Assert.IsTrue(((string)actual["name"]) == "test");
    }

    [TestMethod()]
    public void ObjectToDictionary_should_return_empty_Dictionary_if_given_object_is_null()
    {
      IDictionary<string, object> actual = 
        MVCHelperUtilities.ObjectToDictionary(null);

      Assert.IsTrue(actual.Count == 0);
    }
    #endregion
  }
}
